#ifndef _KNOTSHELPER_H_
#define _KNOTSHELPER_H_

#include <vector>
#include <set>
#include <numeric>
#include "Numtool.h"

template<class T>
std::vector<T> aveknt(const std::vector<T>& oknt, const int k);

template<class T>
std::vector<T> augknt(const std::vector<T>& oknt, const int k);

template<class T>
std::vector<T> aptknt(const std::vector<T>& oknt, const int k);

template<>
std::vector<double> aveknt(const std::vector<double>& oknt, const int k){
  std::vector<double> res;
  const int num = oknt.size();
  if (num <= k)
    return res;
  auto it1 = (oknt.cbegin() + 1);
  auto it2 = (oknt.cbegin() + k);
  for(;it2 != oknt.cend(); it1++,it2++){
    double sum = std::accumulate(it1,it2,0.0);
    res.push_back(sum/(k-1));
  }
  return res;
}

template<>
std::vector<double> augknt(const std::vector<double>& oknt, const int k){
  std::vector<double> res;
  std::multiset<double> sknot;
  for(auto it = oknt.cbegin(); it != oknt.cend() ; it++)
    sknot.insert(*it);
  const double d1 = *(oknt.cbegin());
  const double d2 = *(--oknt.cend());
  if (equal(d1,d2))
    return res;
  auto it1 = sknot.upper_bound(d1);
  auto it2 = sknot.lower_bound(d2);
  for (int i = 0 ; i < k ; i++)
    res.push_back(d1);
  for(; it1 != it2; it1++)
    res.push_back(*it1);
  for (int i = 0 ; i < k ; i++)
    res.push_back(d2);
  return res;
}

template<>
std::vector<double> aptknt(const std::vector<double>& oknt, const int k){
  std::vector<double> aknt = aveknt(oknt,k);
  aknt.insert(aknt.begin(),oknt.front());
  aknt.push_back(oknt.back());
  return augknt(aknt,k);
}












#endif // _KNOTSHELPER_H_
